<?php

namespace IDock\Insurance\DBIC;

use IDock\Common\BaseInterface\BuilderInterface;
use IDock\Http\Request;
use IDock\Http\Response;
use IDock\Insurance\DBIC\Request\AllDBICRequest;
use IDock\Insurance\DBIC\Request\LoginTokenRequest;
use IDock\Insurance\DBIC\Request\PolicyPaymentRequest;
use IDock\Insurance\DBIC\Request\RSAPublicKeyRequest;
use IDock\Insurance\DBIC\Response\AllDBICResponse;

class Builder implements BuilderInterface
{

    public function getConfig(): array
    {
        return $this->config;
    }

    protected $config;

    protected $usercode;
    protected $password;
    protected $key;

    protected $module16;
    protected $exponent16;
    protected $passwordRsANoPadding;
    protected $payKey;
    protected $machId;
    protected $goodDirection;
    protected $backCallUrl;

    //需要动态获取
    protected $token;

    private $nonceStr;

    public function execute(Request $request): Response
    {
        /*** @var AllDBICRequest $request */
        $request->loadConfig($this->config);

        $this->nonceStr = (string)(int)(microtime(true) * 1000);

        $request->setRequestId(md5(uniqid()));

        if ($request instanceof PolicyPaymentRequest) {
            $data = $this->generate($request);
            $request->setPreParameter($data);
            $request->setBizParam($data);

        } else {
            $this->sign($request);
        }

        if (!$request instanceof RSAPublicKeyRequest and !$request instanceof LoginTokenRequest) {

            $header = [
                'content-type' => 'application/json;charset=UTF-8',
                'Authorization' =>  'Bearer '.$this->token,
                'source' => '',
            ];
            $request->setHeaders($header);
        }

        return $this->request($request);
    }

    public function generate(Request $request): array
    {
        return $request->generate();
    }


    public function sign(Request $request): Request
    {
        $data = $this->generate($request);

        $data = [
            'body' => $data,
            'nonceStr' => $this->nonceStr,
        ];
        $toSign = json_encode($data['body'], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);

        $sign = self::replace($toSign) . '&' . $this->nonceStr . '&' . $this->key;

        $data['sign'] = strtoupper(md5($sign));

        $request->setPreParameter($data);
        $request->setBizParam($data);

        return $request;
    }

    public function exceptionResponse($request, $errorMessage): Response
    {
        $response = $request->getResponse();

        $response = new $response;
        $response->setCode('500');
        $response->setError($errorMessage);

        return $response;
    }

    public function request(Request $request): Response
    {
        /*** @var AllDBICResponse $response */
        $response = $request->request($request);
        $response->setVisitor($request->getVisitor());

        if ($response->isSuccess()) {
            $response->printerInit();
        }
        return $response;
    }

    /**
     * 数据加密
     * @param Request $request
     */
    public function encrypt(Request $request)
    {

    }

    /**
     * 加密去空格
     * @param string $str
     * @return array|string|string[]
     * @version 4.0
     */
    private static function replace(string $str)
    {
        return str_replace(["\r\n", "\n", "\t", "\r",' '], ['', '', '', '', ''], $str);
    }
}
